Step1: 提取Todo, TodoList 组件
//修改前:
<ul>
{visibleTodos.map(todo =>
<li key={todo.id}
onClick={() =>{
store.dispatch({
type: 'TOGGLE_TODO',
id: todo.id
});
}}
style={{
textDecoration:
todo.completed ?
'line-through' : 'none'
}}>
{todo.text}
</li>
)}
</ul> //**/
//修改后
const Todo = ({
onClick,
completed,
text
}) => (
<li
onClick={onClick}
style={{
textDecoration:
completed ?
'line-through' : 'none'
}}>
{text}
</li>
);
const TodoList = ({
todos,
onTodoClick
}) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul> //**/
);
<TodoList
todos={visibleTodos}
onTodoClick={id =>
store.despatch({
type: 'TOGGLE_TODO',
id
})
} />
Step2: 提取Add Todo 组件
//修改前
<input ref={node => {
this.input = node;
}} />
<button onClick={() => {
store.dispatch({
type: 'ADD_TODO',
text: this.input.value,
id: nextTodoId++
});
}}>
Add Todo
</button>
//修改后
const AddTodo = ({
onAddClick
}) => {
let input;
return (
<div>
<input ref={node => {
input = node;
}} />
<button onClick={() => {
onAddClick(input.value);
input.value = '';
}}>
Add Todo
</button>
</div>
);
};
<AddTodo
onAddClick={ text =>
store.disptch({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
}
/>
//修改前:
const FilterLink = ({filter, children, currentFilter}) => {
if (filter === currentFilter){
return <span>{children}</span>;
}
return (
<a href='#'
onClick={e => {
e.preventDefault();
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}}>
{children}
</a>
);
}
...
<p>
Show:
{' '}
<FilterLink filter='SHOW_ALL' currentFilter={visibilityFilter}>ALL</FilterLink>
{' '}
<FilterLink filter='SHOW_ACTIVE' currentFilter={visibilityFilter}>Active</FilterLink>
{' '}
<FilterLink filter='SHOW_COMPLETED' currentFilter={visibilityFilter}>Completed</FilterLink>
</p>
//修改后:
const Footer = ({
visibilityFilter,
onFilterClick
}) => {
return(
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
onClick={onFilterClick}>ALL</FilterLink>
{' '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
onClick={onFilterClick>Active</FilterLink>
{' '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
onClick={onFilterClick>Completed</FilterLink>
</p>
);
}
const FilterLink = ({
filter,
children,
currentFilter,
onClick //++
}) => {
if (filter === currentFilter){
return <span>{children}</span>;
}
return (
<a href='#'
onClick={ e => {
e.preventDefault();
onClick(filter); //++
}}>
{children}
</a>
);
};
<Footer
visibilityFilter={visibilityFilter}
onFilterClick={filter =>
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
})
}
/>
Step4: 提取TodoApp 组件
//修改前:
class TodoApp extends Component {
render() {
const { todos,visibilityFilter } = this.props;
const visibleTodos = getVisibleTodos(todos,visibilityFilter);
return (
<div>
<input ref={node => {
this.input = node;
}} />
<button onClick={() => {
store.dispatch({
type: 'ADD_TODO',
text: this.input.value,
id: nextTodoId++
});
}}>
Add Todo
</button>
<ul>
{visibleTodos.map(todo =>
<li key={todo.id}
onClick={() =>{
store.dispatch({
type: 'TOGGLE_TODO',
id: todo.id
});
}}
style={{
textDecoration:
todo.completed ?
'line-through' : 'none'
}}>
{todo.text}
</li>
)}
</ul>
<p>
Show:
{' '}
<FilterLink filter='SHOW_ALL' currentFilter={visibilityFilter}>ALL</FilterLink>
{' '}
<FilterLink filter='SHOW_ACTIVE' currentFilter={visibilityFilter}>Active</FilterLink>
{' '}
<FilterLink filter='SHOW_COMPLETED' currentFilter={visibilityFilter}>Completed</FilterLink>
</p>
</div>
);
};
};
//修改后:
// TodoApp 组件
const TodoApp = ({
todos,
visibilityFilter
}) => (
<div>
<AddTodo
onAddClick={text =>
store.dispatch({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
}
/>
<TodoList
todos={getVisibleTodos(todos,visibilityFilter)}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
} />
<Footer
visibilityFilter={visibilityFilter}
onFilterClick={filter => {
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
});
}} />
</div>
);
//最终代码:http://jsbin.com/pusadi/edit?html,js,output